'use strict';

const crypto = require('crypto');
const ERR_CODE = require('../constants/errorCode');
const USER_TABLE = 'user';
const ALBUM_TABLE = 'album';
const PICTURE_TABLE = 'picture';
const TAG_TABLE = 'tag';
const Service = require('egg').Service;

class UserService extends Service {
  async register(email, username, password, verifyCode) {
    const { ctx, app } = this;

    try {
      // 检查 email 有没有被注册
      const result1 = await app.mysql.select(USER_TABLE, {
        columns: [ 'user_id' ],
        where: { email },
        orders: [
          [ 'user_id', 'asc' ],
        ],
        limit: 1,
        offset: 0,
      });
      if (result1.length > 0) throw (ERR_CODE.Register_EmailDuplicate);

      // 检查 username 有没有被注册
      const result2 = await app.mysql.select(USER_TABLE, {
        columns: [ 'user_id' ],
        where: { username },
        orders: [
          [ 'user_id', 'asc' ],
        ],
        limit: 1,
        offset: 0,
      });
      if (result2.length > 0) throw (ERR_CODE.Register_UsernameDuplicate);

      // 检查邮箱验证码是否正确
      const isVerifyCodeValid = await ctx.service.email.checkVerifyCode(email, verifyCode);
      console.log(isVerifyCodeValid);
      if (!isVerifyCodeValid) throw (ERR_CODE.Email_VerificationFail);

      // 密码二次加密
      const passwordMD5 = crypto.createHash('md5').update(password).digest('hex');

      // 注册用户
      const result3 = await app.mysql.insert(USER_TABLE, {
        username,
        password: passwordMD5,
        email,
        is_admin: 0, // 1: 是管理员 0:不是管理员
        create_time: app.mysql.literals.now,
        update_time: app.mysql.literals.now,
      });

      if (result3.affectedRows !== 1) throw (ERR_CODE.Register_DBInsertFail);

      // 新建一个默认相册
      await ctx.service.album.create(result3.insertId, '默认相册', '默认相册，无法删除', 1);

      return true;
    } catch (err) {
      switch (err) {
        case ERR_CODE.Register_EmailDuplicate:
          ctx.throw(422, '注册失败，邮箱已经被占用', {
            errCode: ERR_CODE.Register_EmailDuplicate,
            description: '注册失败，邮箱已经被占用',
          });
          break;
        case ERR_CODE.Register_UsernameDuplicate:
          ctx.throw(422, '注册失败，用户名已经被占用', {
            errCode: ERR_CODE.Register_UsernameDuplicate,
            description: '注册失败，用户名已经被占用',
          });
          break;
        case ERR_CODE.Email_VerificationFail:
          ctx.throw(422, '注册失败,验证码错误', {
            errCode: ERR_CODE.Email_VerificationFail,
          });
          break;
        case ERR_CODE.Register_DBInsertFail:
          ctx.throw(422, '注册失败,数据库插入错误', {
            errCode: ERR_CODE.Register_DBInsertFail,
          });
          break;
        default:
          throw (err);
      }
    }
  }

  async login(id, password) {
    const { ctx, app } = this;

    try {
      // 密码二次加密
      const passwordMD5 = crypto.createHash('md5').update(password).digest('hex');
      // 检查username/email
      const result = await app.mysql.query(`select * from ${USER_TABLE} where username=? or email=?;`, [ id, id ]);
      if (result.length === 0) throw (ERR_CODE.Login_NoUser);
      if (passwordMD5 !== result[0].password) throw (ERR_CODE.Login_WrongPass);

      // 更新登陆时间
      const row = { latest_login_time: app.mysql.literals.now };
      const options = {
        where: {
          user_id: result[0].user_id,
        },
      };
      await app.mysql.update(USER_TABLE, row, options);

      // 返回用户信息
      const { user_id, username, email, is_admin } = result[0];
      return { user_id, username, email, is_admin };
    } catch (err) {
      switch (err) {
        case ERR_CODE.Login_NoUser:
          ctx.throw(422, '登录失败，没有此用户', {
            errCode: ERR_CODE.Login_NoUser,
            description: '没有此用户',
          });
          break;
        case ERR_CODE.Login_WrongPass:
          ctx.throw(422, '登录失败，密码错误', {
            errCode: ERR_CODE.Login_WrongPass,
            description: '密码错误',
          });
          break;
        default:
          throw (err);
      }
    }
  }

  async modifyPassword(email, newPassword, verifyCode) {
    const { ctx, app } = this;
    try {
    // 检查 email 有没有被注册
      const result1 = await app.mysql.select(USER_TABLE, {
        columns: [ 'user_id' ],
        where: { email },
        orders: [
          [ 'user_id', 'asc' ],
        ],
        limit: 1,
        offset: 0,
      });

      if (result1.length !== 1) throw (ERR_CODE.ModifyPwd_WrongEmail);

      // 检查邮箱验证码是否正确
      const isVerifyCodeValid = await ctx.service.email.checkVerifyCode(email, verifyCode);
      if (!isVerifyCodeValid) throw (ERR_CODE.ModifyPwd_WrongVerifyCode);

      // 密码二次加密
      const passwordMD5 = crypto.createHash('md5').update(newPassword).digest('hex');
      // 修改密码
      const row = {
        password: passwordMD5,
        update_time: app.mysql.literals.now,
      };
      const options = {
        where: {
          user_id: result1[0].user_id,
        },
      };
      const result2 = await this.app.mysql.update(USER_TABLE, row, options); // 更新 posts 表中的记录

      if (result2.affectedRows !== 1) throw (ERR_CODE.ModifyPwd_DBUpdateFail);
      return { success: true, userId: result1[0].user_id };
    } catch (err) {
      switch (err) {
        case ERR_CODE.ModifyPwd_WrongEmail:
          ctx.throw(422, '邮箱错误，请输入正确的邮箱', {
            errCode: ERR_CODE.ModifyPwd_WrongEmail,
            description: '邮箱不存在，邮箱错误',
          });
          break;
        case ERR_CODE.ModifyPwd_WrongVerifyCode:
          ctx.throw(422, '修改密码失败,验证码错误', {
            errCode: ERR_CODE.ModifyPwd_WrongVerifyCode,
          });
          break;
        case ERR_CODE.ModifyPwd_DBUpdateFail:
          ctx.throw(422, '修改密码失败，数据库错误', {
            errCode: ERR_CODE.ModifyPwd_DBUpdateFail,
            description: '数据库更新失败',
          });
          break;
        default:
          throw (err);
      }
    }
  }

  async modifyProfile(userId) {
    const { ctx, app } = this;

    // 获取用户信息

    const userInfo = await this.info(userId);
    const oldLink = userInfo.profile_link;

    // 获取文件流
    const stream = await this.ctx.getFileStream();

    // 获取上传的头像链接
    const newLink = await ctx.service.oss.uploadFile('profile', stream);

    // 更新头像链接
    const row = {
      profile_link: newLink,
      update_time: app.mysql.literals.now,
    };
    const options = {
      where: {
        user_id: userId,
      },
    };
    await app.mysql.update(USER_TABLE, row, options);

    // 删除原头像链接
    if (oldLink) await ctx.service.oss.deleteFile(oldLink);

    return newLink;
  }

  async info(userId) {
    const { app } = this;
    // 返回用户信息
    const result = await app.mysql.get(USER_TABLE, { user_id: userId });
    const { username, email, profile_link, is_admin } = result;
    return { username, email, profile_link, is_admin };
  }

  async statistic(userId) {
    const { app } = this;
    const sql1 = `SELECT count(*) AS total FROM ${ALBUM_TABLE} WHERE user_id = '?'`;
    const result1 = await app.mysql.query(sql1, userId);
    const sql2 = `SELECT count(*) AS total FROM ${PICTURE_TABLE} WHERE user_id = '?' AND status != '1'`;
    const result2 = await app.mysql.query(sql2, userId);
    const sql3 = `SELECT count(*) AS total FROM ${TAG_TABLE} WHERE user_id = '?'`;
    const result3 = await app.mysql.query(sql3, userId);
    console.log(result1, result2, result3);
    return { album_total: result1[0].total, pic_total: result2[0].total, tag_total: result3[0].total };


  }
}

module.exports = UserService;
